/*
 * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ms.orm.conditions;

import com.ms.common.util.ArrayUtils;
import com.ms.common.util.Assert;
import com.ms.common.util.CollectionUtils;
import com.ms.common.util.StringUtils;
import com.ms.orm.conditions.interfaces.Compare;
import com.ms.orm.conditions.interfaces.Func;
import com.ms.orm.conditions.interfaces.Join;
import com.ms.orm.conditions.interfaces.Nested;
import com.ms.orm.conditions.segments.MergeSegments;
import com.ms.orm.constants.Constants;
import com.ms.orm.constants.StringPool;
import com.ms.orm.enums.SqlKeyword;
import com.ms.orm.enums.SqlLike;
import com.ms.orm.util.MetaDataOperator;
import com.ms.orm.util.SerializationUtils;
import com.ms.orm.util.StringEscape;
import com.ms.orm.util.sql.SqlScriptUtils;
import com.ms.orm.util.sql.SqlUtils;
import javafx.collections.transformation.SortedList;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

import static java.util.stream.Collectors.joining;
import static com.ms.orm.enums.SqlKeyword.*;
import static com.ms.orm.enums.WrapperKeyword.*;

/**
 * 查询条件封装，
 * 实现：
 *  1）查询条件比较接口
 *  2）查询条件内嵌 接口
 *  3）拼接
 *  4）
 *
 *
 * @author hubin miemie HCL
 * @since 2017-05-26
 * T : 实体
 * R : 属性/字段
 * Children : Wrapper
 */
@SuppressWarnings({"unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
    implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {

    /**
     * 占位符
     */
    protected final Children typedThis = (Children) this;



    /**
     * 必要度量, 参数名称序列号
     */
    protected AtomicInteger paramNameSeq;


    /**
     * key = 生成的参数名
     * value = 参数值
     */
    protected Map<String, Object> paramNameValuePairs;

    public List<Object> getParamNameValue() {
        return paramNameValue;
    }

    public Integer[] getColumnsJdbcType() {
        return columnsJdbcType;
    }

    /**
     * 占位符对应的 值
     */
    protected List<Object> paramNameValue;
    /**
     * 占位符对应 属性值 对应的 jdbcTpe
     */
    protected Integer[] columnsJdbcType;


    public Map<String, Integer> getParamNameValueJdbcTypePairs() {
        return paramNameValueJdbcTypePairs;
    }

    /**
     * key = 生成的参数名
     * value_jdbcType = 值jdbc类型
     */
    protected Map<String, Integer> paramNameValueJdbcTypePairs;
    /**
     * 其他
     * 参数别名
     */
    protected SharedString paramAlias;

    protected SharedString lastSql;
    /**
     * SQL注释
     */
    protected SharedString sqlComment;
    /**
     * SQL起始语句
     */
    protected SharedString sqlFirst;
    /**
     * 数据库表映射实体类
     */
    private T entity;

    protected MergeSegments expression;
    /**
     * 实体类型(主要用于确定泛型以及取TableInfo缓存)
     */
    private Class<T> entityClass;

    @Override
    public T getEntity() {
        return entity;
    }

    public Children setEntity(T entity) {
        this.entity = entity;
        return typedThis;
    }

    public Class<T> getEntityClass() {
        if (entityClass == null && entity != null) {
            entityClass = (Class<T>) entity.getClass();
        }
        return entityClass;
    }

    public Children setEntityClass(Class<T> entityClass) {
        if (entityClass != null) {
            this.entityClass = entityClass;
        }
        return typedThis;
    }

    /**
     * 1、把 Map<R, V> params 参数加入到 normal sql片段
     * @param condition   执行条件
     * @param params      map 类型的参数, key 是字段名, value 是字段值
     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段\
     * @param <V>
     * @return
     */
    @Override
    public <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull) {
        if (condition && CollectionUtils.isNotEmpty(params)) {
            params.forEach((k, v) -> {
                if (StringUtils.isNotNull(v)) {
                    eq(k, v);
                } else {
                    if (null2IsNull) {
                        isNull(k);
                    }
                }
            });
        }
        return typedThis;
    }

    /**
     * 2、把 Map<R, V> params 参数加入到 normal sql片段
     * @param condition   执行条件
     * @param filter      返回 true 来允许字段传入比对条件中
     * @param params      map 类型的参数, key 是字段名, value 是字段值
     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段
     * @param <V>
     * @return
     */
    @Override
    public <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
        if (condition && CollectionUtils.isNotEmpty(params)) {
            params.forEach((k, v) -> {
                if (filter.test(k, v)) {
                    if (StringUtils.isNotNull(v)) {
                        eq(k, v);
                    } else {
                        if (null2IsNull) {
                            isNull(k);
                        }
                    }
                }
            });
        }
        return typedThis;
    }

    /**
     * 3、添加 相等 查询条件 sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children eq(boolean condition, R column, Object val) {
        return addCondition(condition, column, EQ, val);
    }

    /**
     * 4、添加不相等查询条件 sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children ne(boolean condition, R column, Object val) {
        return addCondition(condition, column, NE, val);
    }

    /**
     * 5、添加 大于 sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children gt(boolean condition, R column, Object val) {
        return addCondition(condition, column, GT, val);
    }

    /**
     * 6、添加 大于等于 sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children ge(boolean condition, R column, Object val) {
        return addCondition(condition, column, GE, val);
    }

    /**
     * 7、添加小于 查询sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children lt(boolean condition, R column, Object val) {
        return addCondition(condition, column, LT, val);
    }

    /**
     * 8、添加小于 等于查询sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children le(boolean condition, R column, Object val) {
        return addCondition(condition, column, LE, val);
    }

    /**
     * 9、添加 like 查询sql片段
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children like(boolean condition, R column, Object val) {
        return likeValue(condition, LIKE, column, val, SqlLike.DEFAULT);
    }

    /**
     * 10、添加 NOT LIKE
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children notLike(boolean condition, R column, Object val) {
        return likeValue(condition, NOT_LIKE, column, val, SqlLike.DEFAULT);
    }

    /**
     * 11、添加 likeLeft
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children likeLeft(boolean condition, R column, Object val) {
        return likeValue(condition, LIKE, column, val, SqlLike.LEFT);
    }

    /**
     * 12、添加 likeRight
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return
     */
    @Override
    public Children likeRight(boolean condition, R column, Object val) {
        return likeValue(condition, LIKE, column, val, SqlLike.RIGHT);
    }

    /**
     * 13、添加 between
     * @param condition 执行条件
     * @param column    字段
     * @param val1      值1
     * @param val2      值2
     * @return
     */
    @Override
    public Children between(boolean condition, R column, Object val1, Object val2) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), BETWEEN,
            () -> formatParam(null, val1), AND, () -> formatParam(null, val2)));
    }

    /**
     * 14、添加 not between
     * @param condition 执行条件
     * @param column    字段
     * @param val1      值1
     * @param val2      值2
     * @return
     */
    @Override
    public Children notBetween(boolean condition, R column, Object val1, Object val2) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_BETWEEN,
            () -> formatParam(null, val1), AND, () -> formatParam(null, val2)));
    }

    /**
     * 15、添加 and ()
     * @param condition 执行条件
     * @param consumer  消费函数
     * @return
     */
    @Override
    public Children and(boolean condition, Consumer<Children> consumer) {
        return and(condition).addNestedCondition(condition, consumer);
    }

    /**
     * 16、添加 or () 嵌套
     * @param condition 执行条件
     * @param consumer  消费函数
     * @return
     */
    @Override
    public Children or(boolean condition, Consumer<Children> consumer) {
        return or(condition).addNestedCondition(condition, consumer);
    }

    /**
     * 17、嵌套
     * @param condition 执行条件
     * @param consumer  消费函数
     * @return
     */
    @Override
    public Children nested(boolean condition, Consumer<Children> consumer) {
        return addNestedCondition(condition, consumer);
    }

    /**
     * 18、not 嵌套
     * @param condition 执行条件
     * @param consumer  消费函数
     * @return
     */
    @Override
    public Children not(boolean condition, Consumer<Children> consumer) {
        return not(condition).addNestedCondition(condition, consumer);
    }

    /**
     * 19、添加 or
     * @param condition 执行条件
     * @return
     */
    @Override
    public Children or(boolean condition) {
        return maybeDo(condition, () -> appendSqlSegments(OR));
    }

    /**
     * 20、拼接 sql ,如果 values 不为空，则替换 sql 中的占位符
     * @param condition 执行条件
     * @param applySql
     * @param values    数据数组
     * @return
     */
    @Override
    public Children apply(boolean condition, String applySql, Object... values) {
        return maybeDo(condition, () -> appendSqlSegments(APPLY,
            () -> formatSqlMaybeWithParam(applySql, null, values)));
    }

    /**
     * 21、在 最后添加 sql
     * @param condition 执行条件
     * @param lastSql   sql语句
     * @return
     */
    @Override
    public Children last(boolean condition, String lastSql) {
        if (condition) {
            this.lastSql.setStringValue(StringPool.SPACE + lastSql);
        }
        return typedThis;
    }

    /**
     * 22、添加注释
     * @param condition 执行条件
     * @param comment   sql注释
     * @return
     */
    @Override
    public Children comment(boolean condition, String comment) {
        if (condition) {
            this.sqlComment.setStringValue(comment);
        }
        return typedThis;
    }

    /**
     * 23、在首部 添加 sql
     * @param condition 执行条件
     * @param firstSql  起始语句
     * @return
     */
    @Override
    public Children first(boolean condition, String firstSql) {
        if (condition) {
            this.sqlFirst.setStringValue(firstSql);
        }
        return typedThis;
    }

    /**
     * 24、添加 EXISTS + sql
     * @param condition 执行条件
     * @param existsSql sql语句
     * @param values    数据数组
     * @return
     */
    @Override
    public Children exists(boolean condition, String existsSql, Object... values) {
        return maybeDo(condition, () -> appendSqlSegments(EXISTS,
            () -> String.format("(%s)", formatSqlMaybeWithParam(existsSql, null, values))));
    }

    /**
     * 25、添加 notExists
     * @param condition 执行条件
     * @param existsSql sql语句
     * @param values    数据数组
     * @return
     */
    @Override
    public Children notExists(boolean condition, String existsSql, Object... values) {
        return not(condition).exists(condition, existsSql, values);
    }

    /**
     * 26、添加 isNull
     * @param condition 执行条件
     * @param column    字段
     * @return
     */
    @Override
    public Children isNull(boolean condition, R column) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), IS_NULL));
    }

    /**
     * 27、添加 IS NOT NULL
     * @param condition 执行条件
     * @param column    字段
     * @return
     */
    @Override
    public Children isNotNull(boolean condition, R column) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), IS_NOT_NULL));
    }

    /**
     * 28、添加 in  Collection<column>
     * @param condition 执行条件
     * @param column    字段
     * @param coll      数据集合
     * @return
     */
    @Override
    public Children in(boolean condition, R column, Collection<?> coll) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), IN, inExpression(coll,column)));
    }

    /**
     * 29、添加 in array<column>
     * @param condition 执行条件
     * @param column    字段
     * @param values    数据数组
     * @return
     */
    @Override
    public Children in(boolean condition, R column, Object... values) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), IN, inExpression(values,column)));
    }

    /**
     * 30、添加 notIn Collection
     * @param condition 执行条件
     * @param column    字段
     * @param coll      数据集合
     * @return
     */
    @Override
    public Children notIn(boolean condition, R column, Collection<?> coll) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_IN, inExpression(coll,column)));
    }

    /**
     * 31、添加 notIn array
     * @param condition 执行条件
     * @param column    字段
     * @param values    数据数组
     * @return
     */
    @Override
    public Children notIn(boolean condition, R column, Object... values) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_IN, inExpression(values,column)));
    }

    /**
     * 32、添加 in sql
     * @param condition 执行条件
     * @param column    字段
     * @param inValue   sql语句
     * @return
     */
    @Override
    public Children inSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), IN,
            () -> String.format("(%s)", inValue)));
    }

    @Override
    public Children gtSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), GT,
            () -> String.format("(%s)", inValue)));
    }

    @Override
    public Children geSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), GE,
            () -> String.format("(%s)", inValue)));
    }

    @Override
    public Children ltSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), LT,
            () -> String.format("(%s)", inValue)));
    }

    @Override
    public Children leSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), LE,
            () -> String.format("(%s)", inValue)));
    }

    @Override
    public Children notInSql(boolean condition, R column, String inValue) {
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_IN,
            () -> String.format("(%s)", inValue)));
    }

    /**
     * 分组统计
     * @param condition
     * @param column
     * @param columns
     * @return
     */
    @Override
    public Children groupBy(boolean condition, R column, R... columns) {
        return maybeDo(condition, () -> {
            String one = columnToString(column);
            if (ArrayUtils.hasElement(columns)) {
                one += (StringPool.COMMA + columnsToString(columns));
            }
            final String finalOne = one;
            appendSqlSegments(GROUP_BY, () -> finalOne);
        });
    }

    @Override
    @SafeVarargs
    public final Children orderBy(boolean condition, boolean isAsc, R column, R... columns) {
        return maybeDo(condition, () -> {
            final SqlKeyword mode = isAsc ? ASC : DESC;
            //得到结果是: List<ISqlSegment> = {ORDER BY, column, ASC}; 或者是  List<ISqlSegment> = {ORDER BY, column, DESC}
            appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)), mode);
            // 如果用多个需要排序，
            if (ArrayUtils.hasElement(columns)) {
                Arrays.stream(columns).forEach(c -> appendSqlSegments(ORDER_BY,columnToSqlSegment(columnSqlInjectFilter(c)), mode));

            }
        });
    }

    @Override
    public Children groupBy(boolean condition, R column) {
        return maybeDo(condition, () -> appendSqlSegments(GROUP_BY, () -> columnToString(column)));
    }

    @Override
    public Children groupBy(boolean condition, List<R> columns) {
        return maybeDo(condition, () -> appendSqlSegments(GROUP_BY, () -> columnsToString(columns)));
    }

    @Override
    public Children orderBy(boolean condition, boolean isAsc, R column) {
        return maybeDo(condition, () -> appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)),
            isAsc ? ASC : DESC));
    }

    @Override
    public Children orderBy(boolean condition, boolean isAsc, List<R> columns) {
        return maybeDo(condition, () -> columns.forEach(c -> appendSqlSegments(ORDER_BY,
            columnToSqlSegment(columnSqlInjectFilter(c)), isAsc ? ASC : DESC)));
    }

    /**
     * 字段 SQL 注入过滤处理，子类重写实现过滤逻辑
     *
     * @param column 字段内容
     * @return
     */
    protected R columnSqlInjectFilter(R column) {
        return column;
    }

    /**
     * 添加
     * @param condition 执行条件
     * @param sqlHaving sql 语句
     * @param params    参数数组
     * @return
     */
    @Override
    public Children having(boolean condition, String sqlHaving, Object... params) {
        return maybeDo(condition, () -> appendSqlSegments(HAVING,() -> formatSqlMaybeWithParam(sqlHaving, null, params)));
    }

    /**
     *
     * @param condition
     * @param consumer 消费函数
     * @return
     */
    @Override
    public Children func(boolean condition, Consumer<Children> consumer) {
        return maybeDo(condition, () -> consumer.accept(typedThis));
    }

    /**
     * 内部自用
     * <p>NOT 关键词</p>
     */
    protected Children not(boolean condition) {
        return maybeDo(condition, () -> appendSqlSegments(NOT));
    }

    /**
     * 内部自用
     * <p>拼接 AND</p>
     */
    protected Children and(boolean condition) {
        return maybeDo(condition, () -> appendSqlSegments(AND));
    }

    /**
     * 内部自用
     * <p>拼接 LIKE 以及 值</p>
     */
    protected Children likeValue(boolean condition, SqlKeyword keyword, R column, Object val, SqlLike sqlLike) {
        //需要 拆开，否则出现异步执行情况？？？
        Object val_1 = SqlUtils.concatLike(val, sqlLike);
        String valSql = formatParam(null, val_1);
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), keyword,() -> valSql));
    }

    /**
     * 添加 普通查询条件 sql片段
     *
     * @param condition  是否执行
     * @param column     属性字段
     * @param sqlKeyword SQL 关键词
     * @param val        条件值
     */
    protected Children addCondition(boolean condition, R column, SqlKeyword sqlKeyword, Object val) {
        //添加到 normal,sql片段通常是: column sqlKeyword val,比如 column = val
        String sql = formatParam(columnToString(column), val);
        ISqlSegment segment = () -> sql;
        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), sqlKeyword,segment));
    }

    /**
     * 多重嵌套查询条件,
     * @param condition 查询条件值
     */
    protected Children addNestedCondition(boolean condition, Consumer<Children> consumer) {
        return maybeDo(condition, () -> {
            final Children instance = instance();
            consumer.accept(instance);
            //把子类的参数 添加到父类集合中
            if(instance.getParamNameValue()!=null && instance.getParamNameValue().size()>0) {
                this.paramNameValue.addAll(instance.getParamNameValue());
            }
            appendSqlSegments(APPLY, instance);
        });
    }

    /**
     * 子类返回一个自己的新对象
     */
    protected abstract Children instance();

    /**
     * 格式化 sql
     * <p>
     * 支持 "{0}" 这种,或者 "sql {0} sql" 这种
     *
     * @param sqlStr  可能是sql片段
     * @param mapping 例如: "javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler" 这种
     * @param params  参数 ，替换 sqlStr 中的占位符
     * @return sql片段
     */
    @SuppressWarnings("SameParameterValue")
    protected final String formatSqlMaybeWithParam(String sqlStr, String mapping, Object... params) {
        if (StringUtils.isBlank(sqlStr)) {
            // todo 何时会这样?
            return null;
        }
        if (ArrayUtils.hasElement(params)) {
            for (int i = 0; i < params.length; ++i) {
                final String target = Constants.LEFT_BRACE + i + Constants.RIGHT_BRACE;
                sqlStr = sqlStr.replace(target, formatParam(mapping, params[i]));
            }
        }
        return sqlStr;
    }



    /**
     * 处理入参
     * @param mapping
     * @param properName
     * @param param 参数值
     * @return return value =  ?
     */
    protected  final String formatParam(String mapping,String properName, Object param) {
        final String genParamName = "paramName_" + properName + paramNameSeq.incrementAndGet();
        //paramStr = 别名字符串.paramNameValuePairs.genParamName
        paramNameValuePairs.put(genParamName, param);
        paramNameValue.add(param);
        return "?";
    }

    /**
     * 处理入参
     * @param param   参数值
     * @return value =  ?
     */
    protected final String formatParam(String properName, Object param) {
        final String genParamName = "paramName_" + (StringUtils.hasLength(properName)?properName:"")+ paramNameSeq.incrementAndGet();
        //paramStr = 别名字符串.paramNameValuePairs.genParamName
        paramNameValuePairs.put(genParamName, param);
        System.err.println("formatParam==="+param);
        this.paramNameValue.add(param);
        return "?";
    }



    /**
     * 函数化的做事
     * @param condition 做不做
     * @param something 做什么
     * @return Children
     */
    protected final Children maybeDo(boolean condition, DoSomething something) {
        if (condition) {
            something.doIt();
        }
        return typedThis;
    }

    /**
     * 获取in表达式 包含括号
     *
     * @param value 集合
     */
    @Deprecated
    protected ISqlSegment inExpression(Collection<?> value) {
        if (CollectionUtils.isEmpty(value)) {
            return () -> "()";
        }
        return () -> value.stream().map(i -> formatParam(null, i))
            .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
    }

    /**
     * 获取in表达式 包含括号
     *
     * @param value 集合
     */
    protected ISqlSegment inExpression(Collection<?> value,R column) {
        if (CollectionUtils.isEmpty(value)) {
            return () -> "()";
        }
        return () -> value.stream().map(i -> formatParam((String)column, i))
                .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
    }

    /**
     * 获取in表达式 包含括号
     *
     * @param values 数组
     */
    @Deprecated
    protected ISqlSegment inExpression(Object[] values) {
        if (ArrayUtils.hasElement(values)) {
            return () -> "()";
        }
        return () -> Arrays.stream(values).map(i -> formatParam(null, i))
            .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
    }

    /**
     * 获取in表达式 包含括号
     *
     * @param values 数组
     */
    protected ISqlSegment inExpression(Object[] values,R column) {
        if (ArrayUtils.hasElement(values)) {
            return () -> "()";
        }
        return () -> Arrays.stream(values).map(i -> formatParam((String)column, i))
                .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
    }

    /**
     * 必要的初始化
     */
    protected void initNeed() {
        //1、参数序列号生成器
        paramNameSeq = new AtomicInteger(0);
        //2、参数 键值对
        paramNameValuePairs = new HashMap<>(16);
        //3、sql 片段集合，根据该对象可以构建一个完整的 查询sql
        expression = new MergeSegments();
        //4、拼接到 sql最后的 语句
        lastSql = SharedString.emptyString();
        //5、sql注释
        sqlComment = SharedString.emptyString();
        //6、sql开头部分
        sqlFirst = SharedString.emptyString();
        paramNameValueJdbcTypePairs = new HashMap<>();
        this. paramNameValue =  new ArrayList<>();
        columnsJdbcType =  new Integer[20];
    }

    @Override
    public void clear() {
        entity = null;
        paramNameSeq.set(0);
        paramNameValuePairs.clear();
        paramNameValueJdbcTypePairs.clear();
        paramNameValue.clear();
        columnsJdbcType = new Integer[0];
        expression.clear();
        lastSql.toEmpty();
        sqlComment.toEmpty();
        sqlFirst.toEmpty();
    }

    /**
     * 添加 where 片段
     *
     * @param sqlSegments ISqlSegment 数组
     */
    protected void appendSqlSegments(ISqlSegment... sqlSegments) {
        expression.add(sqlSegments);
    }

    /**
     * 是否使用默认注解  OrderBy 排序
     *
     * @return true 使用 false 不使用
     */
    public boolean isUseAnnotationOrderBy() {
        final String _sqlSegment = this.getSqlSegment();
        if (StringUtils.isBlank(_sqlSegment)) {
            return true;
        }
        final String _sqlSegmentToUpperCase = _sqlSegment.toUpperCase();
        return !(_sqlSegmentToUpperCase.contains(Constants.ORDER_BY)
            || _sqlSegmentToUpperCase.contains(Constants.LIMIT));
    }

    @Override
    public String getSqlSegment() {
        return expression.getSqlSegment() + lastSql.getStringValue();
    }

    @Override
    public String getSqlComment() {
        if (StringUtils.isNotBlank(sqlComment.getStringValue())) {
            return "/*" + StringEscape.escapeRawString(sqlComment.getStringValue()) + "*/";
        }
        return null;
    }

    @Override
    public String getSqlFirst() {
        if (StringUtils.isNotBlank(sqlFirst.getStringValue())) {
            return StringEscape.escapeRawString(sqlFirst.getStringValue());
        }
        return null;
    }

    @Override
    public MergeSegments getExpression() {
        return expression;
    }

    public Map<String, Object> getParamNameValuePairs() {
        return paramNameValuePairs;
    }


    public String getParamAlias() {
        return paramAlias == null ? Constants.WRAPPER : paramAlias.getStringValue();
    }

    /**
     * 参数别名设置，初始化时优先设置该值、重复设置异常
     *
     * @param paramAlias 参数别名
     * @return Children
     */
    @SuppressWarnings("unused")
    public Children setParamAlias(String paramAlias) {
        Assert.hasText(paramAlias, "paramAlias can not be empty!");
        Assert.isEmpty(paramNameValuePairs, "Please call this method before working!");
        Assert.isNull(this.paramAlias, "Please do not call the method repeatedly!");
        this.paramAlias = new SharedString(paramAlias);
        return typedThis;
    }

    /**
     * 获取 columnName
     */
    protected final ISqlSegment columnToSqlSegment(R column) {
        return () -> columnToString(column);
    }

    /**
     * 获取 columnName
     */
    protected String columnToString(R column) {
        return (String) column;
    }

    /**
     * 获取 columnNames
     * 比如: id,name,age 等
     *
     * 数组或者list 转成成 column1,column2,column3
     */
    protected String columnsToString(R... columns) {
        return Arrays.stream(columns).map(this::columnToString).collect(joining(StringPool.COMMA));
    }

    /**
     * 多字段转换为逗号 "," 分割字符串
     * @param columns 多字段
     */
    protected String columnsToString(List<R> columns) {
        return columns.stream().map(this::columnToString).collect(joining(StringPool.COMMA));
    }

    @Override
    @SuppressWarnings("all")
    public Children clone() {
        return SerializationUtils.clone(typedThis);
    }

    /**
     * 做事函数
     */
    @FunctionalInterface
    public interface DoSomething {
        void doIt();
    }

}
